home *** CD-ROM | disk | FTP | other *** search
/ Workbench Add-On / Workbench Add-On - Volume 1.iso / BBS-Archive / DiskUtil / CD-ROM / AmiCDROM-1.15.lha / AmiCDROM / cdromemu / cdromemu.c < prev    next >
C/C++ Source or Header  |  1994-09-08  |  7KB  |  283 lines

  1. /* cdromemu.c:
  2.  *
  3.  * Emulates trackdisk.device commands CMD_READ and TD_CHANGESTATE.
  4.  *
  5.  * Based on the example_device program by SAS.
  6.  */
  7.  
  8. #define  _USEOLDEXEC_ 1
  9. #include <exec/types.h>
  10. #include <exec/nodes.h>
  11. #include <exec/memory.h>
  12. #include <exec/resident.h>
  13. #include <exec/libraries.h>
  14. #include <exec/execbase.h>
  15. #include <exec/io.h>
  16. #include <exec/errors.h>
  17. #include <libraries/dos.h>
  18. #include <devices/trackdisk.h>
  19. #include <dos/dostags.h>
  20. #include <utility/tagitem.h>
  21. #include <intuition/intuition.h>
  22. #include <proto/exec.h>
  23. #include <proto/dos.h>
  24. #include <proto/intuition.h>
  25.  
  26. #include <string.h>
  27. #include <stdio.h>
  28. #include <dos.h>
  29.  
  30. #include "cdromemu.h"
  31.  
  32. #ifdef DEBUG
  33. #define BUG(x) x
  34. #define EMIT(x) output?Write (output, x, strlen (x)):0
  35. #else
  36. #define BUG(x) /* ignore */
  37. #endif
  38.  
  39. struct MsgPort *myPort;
  40. extern struct ExecBase *SysBase;
  41.  
  42. struct IntuitionBase* IntuitionBase;
  43.  
  44. struct START_MSG {
  45.         struct Message msg;
  46.         long devbase;
  47. };
  48.  
  49. static char* version = "$VER: " VERSION "\n";
  50.  
  51. void cmd_handler(void)
  52. {
  53.     struct IORequest *ior;
  54.     struct IOExtTD *iotd;
  55.     long input;
  56.     struct Process *proc;   
  57.     struct START_MSG *msg;
  58.     char filename[80];
  59.     static struct EasyStruct easy = {
  60.       sizeof (struct EasyStruct),
  61.       0,
  62.       "cdromemu error",
  63.       NULL,
  64.       "Abort"
  65.     };
  66.     short ok = 1;
  67.     short inserted;
  68.     long res;
  69.     ULONG changenum = 0;
  70.     BUG(long output;)
  71.     BUG(static char buf[100];)
  72.     LONG position;
  73.  
  74.     proc = (struct Process *)FindTask((char *)NULL);
  75.  
  76.     /* get the startup message */
  77.     while((msg = (struct START_MSG *)GetMsg(&proc->pr_MsgPort)) == NULL) 
  78.         WaitPort(&proc->pr_MsgPort);
  79.     
  80.     /* builtin compiler functions to set A4 to the global */
  81.     /* data area */
  82.     putreg(REG_A6, msg->devbase); 
  83.     geta4();
  84.     myPort = CreatePort("CDROMEMU",0);
  85.     ReplyMsg((struct Message *)msg);
  86.  
  87.     if (myPort == NULL) return;
  88.  
  89.     IntuitionBase = (struct IntuitionBase *) OpenLibrary ("intuition.library", 0);
  90.  
  91.     if (GetVar ("CDROM_FILE", filename, 79, 0) < 0) {
  92.       easy.es_TextFormat = "Environment variable CDROM_FILE not defined.";
  93.       if (IntuitionBase)
  94.         EasyRequest (NULL, &easy, NULL, NULL);
  95.       ok = 0;
  96.     }
  97.  
  98.     if (ok) {
  99.       input = Open(filename, MODE_OLDFILE);
  100.       inserted = (input != NULL);
  101.       position = 0;
  102.     }
  103.  
  104.     BUG(output = Open("CON:0/0/640/100/CDROMEMU", MODE_NEWFILE);)
  105.  
  106.     while (1) 
  107.     {
  108.         WaitPort(myPort);
  109.         while (ior = (struct IORequest *)GetMsg(myPort)) 
  110.         {
  111.         short reply = 1;
  112.  
  113.         switch(ior->io_Command) 
  114.             {
  115.                 case CMD_TERM:
  116.             BUG(EMIT("CMD_TERM\n");)
  117.             BUG(if(output)Close(output);)
  118.             if (ok && inserted)
  119.                       Close(input);
  120.                     Forbid();
  121.                     ReplyMsg(&ior->io_Message);
  122.                     return;
  123.         
  124.         case CMD_XXX_REMOVE:
  125.             BUG(EMIT("REMOVE\n");)
  126.             reply = 0;
  127.             if (ok && inserted) {
  128.               Close(input);
  129.               inserted = 0;
  130.               changenum++;
  131.             }
  132.             break;
  133.         
  134.         case CMD_XXX_INSERT:
  135.             BUG(EMIT("INSERT\n");)
  136.             reply = 0;
  137.             if (ok && !inserted) {
  138.               input = Open(filename, MODE_OLDFILE);
  139.               if (input) {
  140.                 inserted = 1;
  141.             changenum++;
  142.             position = 0;
  143.               }
  144.             }
  145.             break;
  146.  
  147.  
  148.             case TD_CHANGESTATE: {
  149.                   struct IOExtTD *iotd = (struct IOExtTD*) ior;
  150.                 iotd->iotd_Req.io_Actual = !inserted;
  151. #ifdef DEBUG
  152.             EMIT ("TD_CHANGESTATE ==> ");
  153.             if (inserted)
  154.                 EMIT ("inserted\n");
  155.             else
  156.                 EMIT ("removed\n");
  157. #endif
  158.               break;
  159.              }
  160.  
  161.             case TD_CHANGENUM: {
  162.                   struct IOExtTD *iotd = (struct IOExtTD*) ior;
  163.                 iotd->iotd_Req.io_Actual = changenum;
  164. #ifdef DEBUG
  165.             sprintf (buf, "TD_CHANGENUM ==> %lu\n", changenum);
  166.             EMIT (buf);
  167. #endif
  168.               break;
  169.              }
  170.  
  171.                 case CMD_READ:
  172.                     iotd = (struct IOExtTD *)ior;
  173.             if (ok && inserted) {
  174.               if (position != iotd->iotd_Req.io_Offset) {
  175.                 res = Seek (input, iotd->iotd_Req.io_Offset - position,
  176.                           OFFSET_CURRENT);
  177.                 if (res < 0) {
  178.                   iotd->iotd_Req.io_Error = 1;
  179.               BUG(EMIT("CMD_READ: Seek error\n");)
  180.                   break;
  181.                 }
  182.             position = iotd->iotd_Req.io_Offset;
  183.               }
  184.                       iotd->iotd_Req.io_Actual = Read(input,
  185.                                              iotd->iotd_Req.io_Data, 
  186.                                              iotd->iotd_Req.io_Length);
  187.               position += iotd->iotd_Req.io_Actual;
  188.             } else
  189.               iotd->iotd_Req.io_Actual = 0;
  190. #ifdef DEBUG
  191.             sprintf (buf, "CMD_READ offset=%lu length=%lu\n actual=%lu\n",
  192.                      iotd->iotd_Req.io_Offset,
  193.                      iotd->iotd_Req.io_Length,
  194.                      iotd->iotd_Req.io_Actual);
  195.             EMIT(buf);
  196. #endif
  197.                     break;
  198.             }
  199.         if (reply)
  200.               ReplyMsg(&ior->io_Message);
  201.         }
  202.     }
  203. }
  204.  
  205.  
  206. int  __saveds __asm __UserDevInit(register __d0 long unit,
  207.                                   register __a0 struct IORequest *ior,
  208.                                   register __a6 struct MyLibrary *libbase)
  209. {
  210.       struct Process *myProc;
  211.       struct START_MSG msg;
  212.       
  213.       if (SysBase->LibNode.lib_Version < 36)
  214.           return 1; /* can only run under 2.0 or greater */ 
  215.       
  216.       myProc = CreateNewProcTags(NP_Entry, cmd_handler,
  217.                                  NP_StackSize, 4096,
  218.                                  NP_Name, "CMD_Handler",
  219.                                  TAG_DONE);
  220.       if (myProc == NULL) 
  221.         return 1;
  222.  
  223.       /* Send the startup message with the library base pointer */
  224.       msg.msg.mn_Length = sizeof(struct START_MSG) - 
  225.                           sizeof (struct Message);
  226.       msg.msg.mn_ReplyPort = CreatePort(0,0);
  227.       msg.msg.mn_Node.ln_Type = NT_MESSAGE;
  228.       msg.devbase = getreg(REG_A6);
  229.       PutMsg(&myProc->pr_MsgPort, (struct Message *)&msg);
  230.       WaitPort(msg.msg.mn_ReplyPort);
  231.  
  232.       if (myPort == NULL) /* CMD_Handler allocates this */
  233.         return NULL;
  234.       
  235.       DeletePort(msg.msg.mn_ReplyPort);
  236.       
  237.       return 0;
  238. }
  239.  
  240.  
  241. void __saveds __asm __UserDevCleanup(register __a0 struct IORequest *ior,
  242.                                      register __a6 struct MyLibrary *libbase)
  243. {
  244.     struct IORequest newior;    
  245.         
  246.     /* send a message to the child process to shut down. */
  247.     newior.io_Message.mn_ReplyPort = CreateMsgPort();
  248.     newior.io_Command = CMD_TERM;
  249.     newior.io_Unit = ior->io_Unit;
  250.  
  251.     PutMsg(myPort, &newior.io_Message);
  252.     WaitPort(newior.io_Message.mn_ReplyPort);
  253.     DeleteMsgPort(newior.io_Message.mn_ReplyPort);
  254.     DeletePort(myPort);
  255. }
  256.  
  257.  
  258. void __saveds __asm DevBeginIO(register __a1 struct IORequest *ior)
  259. {
  260.     ior->io_Error = 0;
  261.  
  262.     ior->io_Flags &= ~IOF_QUICK;
  263.     switch(ior->io_Command) 
  264.     {
  265.         case CMD_READ:
  266.     case CMD_XXX_REMOVE:
  267.     case CMD_XXX_INSERT:
  268.         case TD_CHANGESTATE:
  269.         case TD_CHANGENUM:
  270.           PutMsg(myPort, &ior->io_Message);
  271.           break;
  272.     
  273.         default:
  274.             ior->io_Error = IOERR_NOCMD;
  275.          ReplyMsg(&ior->io_Message);
  276.            break;
  277.     }
  278. }
  279.  
  280. void __saveds __asm DevAbortIO(register __a1 struct IORequest *ior)
  281. {
  282. }
  283.